package br.com.felinelayer.server;

import br.com.felinelayer.common.Communication;
import br.com.felinelayer.common.ICommunicationListener;
import br.com.felinelayer.common.Message;
import br.com.felinelayer.server.application.Application;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Vanius Roberto Bittencourt
 */
public final class ClientServer implements ICommunicationListener {

    public ClientServer( Socket socket ) {
        setSocket( socket );
    }
    private Socket socket;
    private Communication communication;
    private Application application;

    public void setSocket( Socket socket ) {
        this.socket = socket;
        if ( this.getCommunication() == null ) {
            setCommunication( new Communication( this ) );
        }
    }

    public synchronized Communication getCommunication() {
        return communication;
    }

    public void setCommunication( Communication communication ) {
        this.communication = communication;
        this.communication.isServer = true;
    }

    public void setApplication( Application application ) {
        this.application = application;
        application.setClient( this );
        Message c = new Message( "ConnectingApplicationName" );
        c.setValueByName( "ApplicationName", application.getApplicationName() );
        processMessageReceived( c );
    }

    @Override
    public Socket getSocket() {
        return socket;
    }

    public void disconnect() {
        getCommunication().disconnect();
    }

    public void sendMessage( Message message ) {
        getCommunication().sendMessage( message );
    }

    public ClientServer beginBatch() {
        getCommunication().beginBatch();
        return this;
    }

    public boolean inBacth() {
        return getCommunication().inBatch();
    }

    public ClientServer endBatch() {
        getCommunication().endBatch();
        return this;
    }

    public Message inquire( Message message ) {
        return getCommunication().inquire( message );
    }

    // ESSTE MÉTODO É EXECUTADO NUMA THREAD SEPARADA DA RECEPÇÃO DO SOCKET.
    // SE SIM, ENTÃO A RECEPÇÃO DO CLIENT PRECISAR CRIAR UM RUNNABLE E PASSAR 
    // PARA O INVOKELATER?
    // REVISAR ESTE processMessageReceived COM O DO client.Client
    /**
     *
     * Process message receiveid.<br>
     * This cannot be synchronized because has reentrance
     *
     * @param message
     */
    @Override
    public void processMessageReceived( Message message ) {
        try {
            for ( Message m : Message.convertToArray( message ) ) {
                if ( getApplication() != null ) {
                    getApplication().messageReceived( m );
                }
                getCommunication().finishMessageReceived( m );
            }
        } catch ( Exception ex ) {
            Logger.getLogger( ClientServer.class.getName() ).log( Level.SEVERE, null, ex );
        }
    }

    /**
     * @return the application
     */
    public synchronized Application getApplication() {
        return application;
    }
}
